<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- 
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License. 
-->
<html>
<head>
    <link type="text/css" rel="stylesheet" href="https://struts.apache.org/css/default.css">
    <style type="text/css">
        .dp-highlighter {
            width:95% !important;
        }
    </style>
    <style type="text/css">
        .footer {
            background-image:      url('https://cwiki.apache.org/confluence/images/border/border_bottom.gif');
            background-repeat:     repeat-x;
            background-position:   left top;
            padding-top:           4px;
            color:                 #666;
        }
    </style>
    <link href='https://struts.apache.org/highlighter/style/shCoreStruts.css' rel='stylesheet' type='text/css' />
    <link href='https://struts.apache.org/highlighter/style/shThemeStruts.css' rel='stylesheet' type='text/css' />
    <script src='https://struts.apache.org/highlighter/js/shCore.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushPlain.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushXml.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushJava.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushJScript.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushGroovy.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushBash.js' type='text/javascript'></script>
    <script type="text/javascript">
        SyntaxHighlighter.defaults['toolbar'] = false;
        SyntaxHighlighter.all();
    </script>
    <script type="text/javascript" language="javascript">
        var hide = null;
        var show = null;
        var children = null;

        function init() {
            /* Search form initialization */
            var form = document.forms['search'];
            if (form != null) {
                form.elements['domains'].value = location.hostname;
                form.elements['sitesearch'].value = location.hostname;
            }

            /* Children initialization */
            hide = document.getElementById('hide');
            show = document.getElementById('show');
            children = document.all != null ?
                    document.all['children'] :
                    document.getElementById('children');
            if (children != null) {
                children.style.display = 'none';
                show.style.display = 'inline';
                hide.style.display = 'none';
            }
        }

        function showChildren() {
            children.style.display = 'block';
            show.style.display = 'none';
            hide.style.display = 'inline';
        }

        function hideChildren() {
            children.style.display = 'none';
            show.style.display = 'inline';
            hide.style.display = 'none';
        }
    </script>
    <title>Security</title>
</head>
<body onload="init()">
<table border="0" cellpadding="2" cellspacing="0" width="100%">
    <tr class="topBar">
        <td align="left" valign="middle" class="topBarDiv" align="left" nowrap>
            &nbsp;<a href="home.html">Home</a>&nbsp;&gt;&nbsp;<a href="guides.html">Guides</a>&nbsp;&gt;&nbsp;<a href="core-developers-guide.html">Core Developers Guide</a>&nbsp;&gt;&nbsp;<a href="security.html">Security</a>
        </td>
        <td align="right" valign="middle" nowrap>
            <form name="search" action="https://www.google.com/search" method="get">
                <input type="hidden" name="ie" value="UTF-8" />
                <input type="hidden" name="oe" value="UTF-8" />
                <input type="hidden" name="domains" value="" />
                <input type="hidden" name="sitesearch" value="" />
                <input type="text" name="q" maxlength="255" value="" />
                <input type="submit" name="btnG" value="Google Search" />
            </form>
        </td>
    </tr>
</table>

<div id="PageContent">
    <div class="pageheader" style="padding: 6px 0px 0px 0px;">
        <!-- We'll enable this once we figure out how to access (and save) the logo resource -->
        <!--img src="/wiki/images/confluence_logo.gif" style="float: left; margin: 4px 4px 4px 10px;" border="0"-->
        <div style="margin: 0px 10px 0px 10px" class="smalltext">Apache Struts 2 Documentation</div>
        <div style="margin: 0px 10px 8px 10px"  class="pagetitle">Security</div>

        <div class="greynavbar" align="right" style="padding: 2px 10px; margin: 0px;">
            <a href="https://cwiki.apache.org/confluence/pages/editpage.action?pageId=34024409">
                <img src="https://cwiki.apache.org/confluence/images/icons/notep_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Edit Page"></a>
            <a href="https://cwiki.apache.org/confluence/pages/editpage.action?pageId=34024409">Edit Page</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/listpages.action?key=WW">
                <img src="https://cwiki.apache.org/confluence/images/icons/browse_space.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Browse Space"></a>
            <a href="https://cwiki.apache.org/confluence/pages/listpages.action?key=WW">Browse Space</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/createpage.action?spaceKey=WW&fromPageId=34024409">
                <img src="https://cwiki.apache.org/confluence/images/icons/add_page_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Add Page"></a>
            <a href="https://cwiki.apache.org/confluence/pages/createpage.action?spaceKey=WW&fromPageId=34024409">Add Page</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/createblogpost.action?spaceKey=WW&fromPageId=34024409">
                <img src="https://cwiki.apache.org/confluence/images/icons/add_blogentry_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Add News"></a>
            <a href="https://cwiki.apache.org/confluence/pages/createblogpost.action?spaceKey=WW&fromPageId=34024409">Add News</a>
        </div>
    </div>

    <div class="pagecontent">
        <div class="wiki-content">
            <div id="ConfluenceContent"><p><style type="text/css">/*<![CDATA[*/
div.rbtoc1440493861559 {padding: 0px;}
div.rbtoc1440493861559 ul {list-style: disc;margin-left: 0px;}
div.rbtoc1440493861559 li {margin-left: 0px;padding-left: 0px;}

/*]]>*/</style></p><div class="toc-macro rbtoc1440493861559">
<ul class="toc-indentation"><li><a shape="rect" href="#Security-Securitytips">Security tips</a>
<ul class="toc-indentation"><li><a shape="rect" href="#Security-RestrictaccesstotheConfigBrowser">Restrict access to the Config Browser</a></li><li><a shape="rect" href="#Security-Don'tmixdifferentaccesslevelsinthesamenamespace">Don't mix different access levels in the same namespace</a></li><li><a shape="rect" href="#Security-NeverexposeJSPfilesdirectly">Never expose JSP files directly</a></li><li><a shape="rect" href="#Security-DisabledevMode">Disable devMode</a></li></ul>
</li><li><a shape="rect" href="#Security-Internalsecuritymechanism">Internal security mechanism</a>
<ul class="toc-indentation"><li><a shape="rect" href="#Security-Accessingstaticmethods">Accessing static methods</a></li><li><a shape="rect" href="#Security-OGNLisusedtocallaction'smethods">OGNL is used to call action's methods</a></li><li><a shape="rect" href="#Security-Accepted/Excludedpatterns">Accepted / Excluded patterns</a></li></ul>
</li></ul>
</div><h3 id="Security-Securitytips">Security tips</h3><p>The Apache Struts 2 doesn't provide any security mechanism - it is just a pure web framework. Below are few tips you should consider during application development with the Apache Struts 2.</p><h4 id="Security-RestrictaccesstotheConfigBrowser">Restrict access to the Config Browser</h4><p><a shape="rect" href="config-browser-plugin.html">Config Browser Plugin</a>&#160;exposes internal configuration and should be used only during development phase. If you must use it on production site, we strictly recommend restricting access to it - you can use &#160;Basic Authentication or any other security mechanism (e.g. <a shape="rect" class="external-link" href="http://shiro.apache.org/">Apache Shiro</a>)</p><h4 id="Security-Don'tmixdifferentaccesslevelsinthesamenamespace">Don't mix different access levels in the same namespace</h4><p>Very often access to different resources is controlled based on URL patterns, see snippet below. Because of that you cannot mix actions with different security levels in the same namespace. Always group actions in one namespace by security level.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">    &lt;security-constraint&gt;
        &lt;web-resource-collection&gt;
            &lt;web-resource-name&gt;admin&lt;/web-resource-name&gt;
            &lt;url-pattern&gt;/secure/*&lt;/url-pattern&gt;
        &lt;/web-resource-collection&gt;
        &lt;auth-constraint&gt;
            &lt;role-name&gt;admin&lt;/role-name&gt;
        &lt;/auth-constraint&gt;
    &lt;/security-constraint&gt;
</pre>
</div></div><h4 id="Security-NeverexposeJSPfilesdirectly">Never expose JSP files directly</h4><p>You must always hide JSP file behind an action, you cannot allow for direct access to the JSP files as this can leads to unpredictable security vulnerabilities. You can achieve this by putting all your JSP files under the&#160;<code>WEB-INF</code> folder - most of the JEE containers restrict access to files placed under the&#160;<code>WEB-INF</code> folder. Second option is to add security constraint to the <code>web.xml</code>&#160;file:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;!-- Restricts access to pure JSP files - access available only via Struts action --&gt;
&lt;security-constraint&gt;
    &lt;display-name&gt;No direct JSP access&lt;/display-name&gt;
    &lt;web-resource-collection&gt;
        &lt;web-resource-name&gt;No-JSP&lt;/web-resource-name&gt;
        &lt;url-pattern&gt;*.jsp&lt;/url-pattern&gt;
    &lt;/web-resource-collection&gt;
    &lt;auth-constraint&gt;
        &lt;role-name&gt;no-users&lt;/role-name&gt;
    &lt;/auth-constraint&gt;
&lt;/security-constraint&gt;

&lt;security-role&gt;
    &lt;description&gt;Don't assign users to this role&lt;/description&gt;
    &lt;role-name&gt;no-users&lt;/role-name&gt;
&lt;/security-role&gt;</pre>
</div></div><p>The best approach is to used the both solutions.</p><h4 id="Security-DisabledevMode">Disable devMode</h4><p>The&#160;<code style="line-height: 1.4285715;">devMode</code> is very useful option back can expose your application presenting too many informations of application's internals. Please always disable the&#160;<code>devMode</code> before deploying your application to a production environment.</p><h3 id="Security-Internalsecuritymechanism">Internal security mechanism</h3><p>The Apache Struts 2 contains internal security manager which blocks access to particular classes and Java packages - it's a OGNL-wide mechanism which means it affects any aspect of the framework ie. incoming parameters, expressions used in JSPs, etc.</p><p>The defaults are as follow:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">    &lt;constant name="struts.excludedClasses"
              value="
                java.lang.Object,
                java.lang.Runtime,
                java.lang.System,
                java.lang.Class,
                java.lang.ClassLoader,
                java.lang.Shutdown,
                ognl.OgnlContext,
                ognl.MemberAccess,
                ognl.ClassResolver,
                ognl.TypeConverter,
                com.opensymphony.xwork2.ActionContext" /&gt;
    &lt;!-- this must be valid regex, each '.' in package name must be escaped! --&gt;
    &lt;constant name="struts.excludedPackageNamePatterns" value="^java\.lang\..*,^ognl.*,^javax.*" /&gt;</pre>
</div></div><p>Any expression or target which evaluates to one of these will be blocked and you see a WARN in logs:</p><div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>[WARNING] Target class [class example.MyBean] or declaring class of member type [public example.MyBean()] are excluded!</pre>
</div></div><p>In that case&#160;<code>new MyBean()</code> was used to create a new instance of class (inside JSP) - it's blocked because&#160;<code>target</code> of such expression is evaluated to&#160;<code>java.lang.Class</code></p><div class="confluence-information-macro confluence-information-macro-note"><span class="aui-icon aui-icon-small aui-iconfont-warning confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>It is possible to redefine the above constants in <code>struts.xml</code> but try to avoid this and rather change design of your application!</p></div></div><h4 id="Security-Accessingstaticmethods">Accessing static methods</h4><div class="confluence-information-macro confluence-information-macro-warning"><span class="aui-icon aui-icon-small aui-iconfont-error confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>Support for accessing static methods from expression will be disabled soon, please consider re-factoring your application to avoid further problems! Please check <a shape="rect" class="external-link" href="https://issues.apache.org/jira/browse/WW-4348">WW-4348</a>.</p></div></div><h4 id="Security-OGNLisusedtocallaction'smethods">OGNL is used to call action's methods</h4><p>This can impact actions which have large inheritance hierarchy and use the same method's name throughout the hierarchy, this was reported as an issue <a shape="rect" class="external-link" href="https://issues.apache.org/jira/browse/WW-4405">WW-4405</a>. See the example below:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class RealAction extends BaseAction {  
    @Action("save")
    public String save() throws Exception {
        super.save();
        return SUCCESS;
    }
}    
&#160;
public class BaseAction extends AbstractAction {
    public String save() throws Exception {
        save(Double.MAX_VALUE);
        return SUCCESS;
    }
}
&#160;
public abstract class AbstractAction extends ActionSupport {
    protected void save(Double val) {
        // some logic
    }
}</pre>
</div></div><p>In such case OGNL cannot properly map which method to call when request is coming. This is do the OGNL limitation. To solve the problem don't use the same method's names through the hierarchy, you can simply change the action's method from&#160;<code>save()</code> to&#160;<code>saveAction()</code>&#160;and leaving annotation as is to allow&#160;<span style="line-height: 1.4285715;">call this action via&#160;</span><code style="line-height: 1.4285715;">/save.action</code><span style="line-height: 1.4285715;"> request.</span></p><h4 id="Security-Accepted/Excludedpatterns"><span style="line-height: 1.4285715;">Accepted / Excluded patterns</span></h4><p><span style="line-height: 1.4285715;">As from version 2.3.20 the framework provides two new interfaces which are used to accept / exclude param names and values -&#160;<a shape="rect" class="external-link" href="http://struts.apache.org/maven/xwork-core/apidocs/com/opensymphony/xwork2/security/AcceptedPatternsChecker.html">AcceptedPatternsChecker</a> and&#160;<a shape="rect" class="external-link" href="http://struts.apache.org/maven/xwork-core/apidocs/com/opensymphony/xwork2/security/ExcludedPatternsChecker.html">ExcludedPatternsChecker</a> with default implementations. These two interfaces are used by&#160;<a shape="rect" href="parameters-interceptor.html">Parameters Interceptor</a> and&#160;<a shape="rect" href="cookie-interceptor.html">Cookie Interceptor</a> to check if param can accepted or must be excluded. If you were using&#160;<code>excludeParams</code> previously please compare patterns used by you with these provided by the framework in default implementation.</span></p></div>
        </div>

        
    </div>
</div>
<div class="footer">
    Generated by CXF SiteExporter
</div>
</body>
</html>
